#include <buola/scene/geodes/cpointgraph.h>
#include <buola/scene/techniques/cpointtechnique.h>

namespace buola { namespace scene {

CPointGraph::CPointGraph()
    :   mHaveData(false)
    ,   mTechnique(CLineTechnique::Get())
{
}

CPointGraph::CPointGraph(graph::CGraph<buola::mat::CVec3d> pGraph)
    :   CPointGraph()
{
    SetGraph(std::move(pGraph));
}

CPointGraph::~CPointGraph()
{
    
}

void CPointGraph::SetGraph(graph::CGraph<buola::mat::CVec3d> pGraph)
{
    mGraph=std::move(pGraph);
    mHaveData=false;
}

void CPointGraph::Render(CRenderContext &pContext)
{
    if(!mHaveData)
        GenerateData();
    
    mTechnique->Prepare(pContext);

    glBindBuffer(GL_ARRAY_BUFFER,mVertexData.GetVBO());
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    mVertexData.SetVertexAttrib(0,FIELD_POSITION);
    mVertexData.SetVertexAttrib(1,FIELD_AMBIENT);

    glDisable(GL_BLEND);
    glDrawArrays(GL_LINES,0,num_edges(mGraph)*2);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
}

void CPointGraph::GenerateData()
{
    if(mHaveData) return;
    
    if(!mVertexData)
    {
        mVertexData.AddField<float>(FIELD_POSITION,3);
        mVertexData.AddField<float>(FIELD_AMBIENT,4);
        
        mVertexData.Resize(400000);//mGraph.size());
    }

    struct ATTRIBUTE_PACKED LVertex
    {
        float x,y,z;
        float r,g,b,a;
    };
    
    LVertex *lVertices=mVertexData.Map<LVertex>();
    
    int i=0;
    auto lPair=edges(mGraph);
    for(const auto &e : range(lPair.first,lPair.second))
    {
        lVertices[i].x=mGraph[source(e,mGraph)].x();
        lVertices[i].y=mGraph[source(e,mGraph)].y();
        lVertices[i].z=mGraph[source(e,mGraph)].z();

        lVertices[i].r=1.0;
        lVertices[i].g=1.0;
        lVertices[i].b=1.0;
        lVertices[i].a=1.0;
        i++;
        
        lVertices[i].x=mGraph[target(e,mGraph)].x();
        lVertices[i].y=mGraph[target(e,mGraph)].y();
        lVertices[i].z=mGraph[target(e,mGraph)].z();

        lVertices[i].r=1.0;
        lVertices[i].g=1.0;
        lVertices[i].b=1.0;
        lVertices[i].a=1.0;
        i++;
    }
    
    mVertexData.Unmap();
    
    mHaveData=true;
}

/*namespace scene*/ } /*namespace buola*/ }
